﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using Microsoft.Xna.Framework.Media;

namespace Coding4Fun.SlideShow
{
    public partial class Player : UserControl
    {
        /// <summary>
        /// Defines the different states that the Player can have
        /// </summary>
        public enum PlayerStates
        {
            Stopped,
            Playing,
            Paused
        }

        public event RoutedEventHandler Stopped;
        public event RoutedEventHandler FailedToLoad;

        private PlayerStates _playerState = PlayerStates.Stopped;
        /// <summary>
        /// Gets or Sets the value for the Player's State
        /// </summary>
        public PlayerStates PlayerState { get { return _playerState; } set { _playerState = value; } }
        
        /// <summary>
        /// The index of the currently displayed picture of the album
        /// </summary>
        private int _currentPictureIndex;

        /// <summary>
        /// The new slide that will display under the old slide waiting to display
        /// </summary>
        private Slide _newSlide;

        /// <summary>
        /// The old slide that is currently display waiting to transition out
        /// </summary>
        private Slide _oldSlide;

        /// <summary>
        /// Usercontrol Constructor
        /// </summary>
        public Player()
        {
            // Required to initialize variables
            InitializeComponent();

            App.SlideDurationCompleting += SlideHandler_SlideCompleting;
        }

        /// <summary>
        /// Event handler that fires when a slide duration has completed.
        /// Slide to next picture
        /// </summary>
        void SlideHandler_SlideCompleting(object sender, EventArgs e)
        {
            SlidePicture(int.MinValue);
        }
		
        /// <summary>
        /// Plays an Album
        /// </summary>
        public void PlayAlbum()
        {
            PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled;

            PlayerState = PlayerStates.Playing;

            _currentPictureIndex = 0;

            uxSBIntro.Begin();

            ShowPicture();
        }

        /// <summary>
        /// Slides to the next or previous picture depending on the angle of the flick gesture passed
        /// </summary>
        /// <param name="angle">Angle of the Flick Gesture</param>
        public void SlidePicture(double angle)
        {
            if (angle != int.MinValue && (angle > Convert.ToDouble(Settings.ForwardGestureGreaterThanAngle) || angle < Convert.ToDouble(Settings.ForwardGestureLessThanAngle)))
                _currentPictureIndex = _currentPictureIndex == 0 ? App.SelectedAlbum.Count - 1 : _currentPictureIndex - 1;
            else
                _currentPictureIndex = _currentPictureIndex >= App.SelectedAlbum.Count - 1 ? 0 : _currentPictureIndex + 1;

            ShowPicture();

        }

        /// <summary>
        /// Displays the picture of the currentPictureIndex
        /// </summary>
        private void ShowPicture()
        {
            if (App.SelectedAlbum == null)
            {
                if(FailedToLoad != null)
                    FailedToLoad.Invoke(this, null);

                return;
            }

            if (_newSlide != null)
            {
                _oldSlide = _newSlide;
            }

            _newSlide = new Slide();

            var bitmap = new WriteableBitmap(800, 800);

            using (var source = App.SelectedAlbum[_currentPictureIndex].GetImage())
                bitmap.SetSource(source);

            _newSlide.SetImage(bitmap);
            _newSlide.UpdateLayout();
            _newSlide.Begin();

            if (_oldSlide != null)
                _oldSlide.uxSBOutro.Begin();

            uxSlides.Children.Insert(0, _newSlide);
            while (uxSlides.Children.Count > 2)
            {
                ((Slide)uxSlides.Children[uxSlides.Children.Count - 1]).ForceRemove();
            }
        }

        // Stops all Storyboards
        public void Stop()
        {
            PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Enabled;
            uxSlides.Children.Where(result => result is Slide).ToList().ForEach(slide => ((Slide)slide).Stop());
            uxSlides.Children.Clear();
            uxSBIntro.Stop();

            PlayerState = PlayerStates.Stopped;

            if (Stopped != null)
            {
                var args = new RoutedEventArgs();

                Stopped.Invoke(this, args);
            }
        }

        /// <summary>
        /// Pauses all Storyboards
        /// </summary>
        public void Pause()
        {
            uxSlides.Children.Where(result => result is Slide).ToList().ForEach(slide => ((Slide)slide).Pause());

            PlayerState = PlayerStates.Paused;
        }

        /// <summary>
        /// Resumes all Storyboards
        /// </summary>
        public void Resume()
        {
            uxSlides.Children.Where(result => result is Slide).ToList().ForEach(slide => ((Slide)slide).Resume());

            PlayerState = PlayerStates.Playing;
        }

		private void LayoutRoot_DoubleTap(object sender, System.Windows.Input.GestureEventArgs e)
		{
			if (PlayerState == PlayerStates.Playing && uxSBIntro.GetCurrentState() != ClockState.Active)
			{
				Stop();
			}
		}

		private void LayoutRoot_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
		{
			if (e.IsInertial)
			{
				if (PlayerState == PlayerStates.Paused)
					Resume();


				SlidePicture(Math.Atan(e.TotalManipulation.Translation.Y / e.TotalManipulation.Translation.X) * 180 / Math.PI);
				//SlidePicture(Angle(0, 0, e.TotalManipulation.Translation.X,  e.TotalManipulation.Translation.Y) );
			}
		}

		//public double Angle(double x1, double y1, double x2, double y2)
		//{

		//    // Negate X and Y values 
		//    double pxRes = x2 - x1;
		//    double pyRes = y2 - y1;
		//    double angle;

		//    // Calculate the angle 
		//    if (pxRes == 0.0)
		//    {
		//        if (pxRes == 0.0)
		//        {
		//            angle = 0.0;
		//        }
		//        else if (pyRes > 0.0)
		//        {
		//            angle = Math.PI / 2.0;
		//        }
		//        else
		//        {
		//            angle = Math.PI * 3.0 / 2.0;
		//        }
		//    }
		//    else if (pyRes == 0.0)
		//    {
		//        angle = pxRes > 0.0 ? 0.0 : Math.PI;
		//    }

		//    else
		//    {
		//        if (pxRes < 0.0)
		//            angle = Math.Atan(pyRes/pxRes) + Math.PI;
		//        else if (pyRes < 0.0)
		//        {
		//            angle = Math.Atan(pyRes / pxRes) + (2 * Math.PI);

		//        }
		//        else
		//        {
		//            angle = Math.Atan(pyRes / pxRes);
		//        }
		//    }

		//    // Convert to degrees 
		//    angle = angle * 180 / Math.PI; 
			
		//    return angle;
		//} 

    }
}
